﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DomainDriver.CommonUtilities.Collections;
using DomainDriver.DomainModeling.DomainObjects;

namespace AutomotivePricingModel.Dealers
{
    public partial class Dealer : KeyedDomainObjectBase<Guid, Dealer>
    {
        private string m_Name;
        private Dictionary<Guid, DealerBrandRelation> m_BrandsRepresented;
        private Dictionary<Guid, DealerVehicleRelation> m_VehiclesInStock;

        public Dealer()
        {
            m_Key = Guid.NewGuid();
            m_Name = string.Empty;
            m_BrandsRepresented = new Dictionary<Guid, DealerBrandRelation>();
            m_VehiclesInStock = new Dictionary<Guid, DealerVehicleRelation>();
        }

        public string Name
        {
            get { return m_Name; }
            set { m_Name = value; }
        }

        public IList<Guid> BrandsRepresented
        {
            get { return new List<Guid>(m_BrandsRepresented.Keys); }
        }

        public bool HasBrand(Guid brandId)
        {
            return m_BrandsRepresented.ContainsKey(brandId);
        }

        public void AddBrand(Guid brandId)
        {
            if (m_BrandsRepresented.ContainsKey(brandId))
            { throw new ApplicationException(); }

            DealerBrandRelation brandRelation = new DealerBrandRelation(m_Key, brandId);
            m_BrandsRepresented.Add(brandId, brandRelation);
        }

        public void RemoveBrand(Guid brandId)
        {
            if (!m_BrandsRepresented.ContainsKey(brandId))
            { throw new ApplicationException(); }

            m_BrandsRepresented.Remove(brandId);
        }

        public IList<Guid> VehiclesInStock
        {
            get { return new List<Guid>(m_VehiclesInStock.Keys); }
        }

        public IDictionary<Guid, int> NumberOfVehiclesInStock
        {
            get
            {
                Dictionary<Guid, int> numberOfVehiclesInStock = new Dictionary<Guid, int>();
                foreach (DealerVehicleRelation vehicleRelation in m_VehiclesInStock.Values)
                {
                    numberOfVehiclesInStock.Add(vehicleRelation.RelatedVehicleId, vehicleRelation.VehicleCount);
                }
                return numberOfVehiclesInStock;
            }
        }

        public bool HasVehicle(Guid vehicleId)
        {
            return m_VehiclesInStock.ContainsKey(vehicleId);
        }

        public int GetNumberOfVehiclesInStock(Guid vehicleId)
        {
            if (!m_VehiclesInStock.ContainsKey(vehicleId))
            { throw new ApplicationException(); }
            return m_VehiclesInStock[vehicleId].VehicleCount;
        }

        public int GetNumberOfVehiclesInStock()
        {
            int totalStock = 0;
            foreach (DealerVehicleRelation vehicleRelation in m_VehiclesInStock.Values)
            {
                totalStock += vehicleRelation.VehicleCount;
            }
            return totalStock;
        }

        public void SetNumberOfVehiclesInStock(Guid vehicleId, int numberInStock)
        {
            if (!m_VehiclesInStock.ContainsKey(vehicleId))
            {
                DealerVehicleRelation vehicleRelation = new DealerVehicleRelation(m_Key, vehicleId, numberInStock);
                m_VehiclesInStock.Add(vehicleId, vehicleRelation);
            }
            else
            {
                m_VehiclesInStock[vehicleId].VehicleCount = numberInStock;
            }
        }

        public void RemoveVehicleFromStock(Guid vehicleId)
        {
            if (!m_VehiclesInStock.ContainsKey(vehicleId))
            { return; }
            m_VehiclesInStock.Remove(vehicleId);
        }

        #region DomainObject Methods

        public override Dealer Copy()
        {
            Dealer copy = new Dealer();
            CopyTo(copy);
            return copy;
        }

        public override void CopyTo(Dealer otherObject)
        {
            if (otherObject.m_Key != m_Key)
            { otherObject.m_Key = m_Key; }
            if (otherObject.m_Name != m_Name)
            { otherObject.m_Name = m_Name; }
            CopyDictionaryToOtherInPlace<Guid, DealerBrandRelation>(otherObject, (DealerBrandRelation rel) => rel.RelatedBrandId, (Dealer obj) => obj.m_BrandsRepresented);
            CopyDictionaryToOtherInPlace<Guid, DealerVehicleRelation>(otherObject, (DealerVehicleRelation rel) => rel.RelatedVehicleId, (Dealer obj) => obj.m_VehiclesInStock);
        }

        public override bool Equals(Dealer otherObject)
        {
            if (otherObject.m_Key != m_Key)
            { return false; }
            if (otherObject.m_Name != m_Name)
            { return false; }
            if (!CollectionUtilities.AreUnorderedDictionariesEqual<Guid, DealerBrandRelation>(otherObject.m_BrandsRepresented, m_BrandsRepresented))
            { return false; }
            if (!CollectionUtilities.AreUnorderedDictionariesEqual<Guid, DealerVehicleRelation>(otherObject.m_VehiclesInStock, m_VehiclesInStock))
            { return false; }
            return true;
        }

        #endregion
    }
}